
package org.amuthu.expression.terminal;

import org.amuthu.parser.ExpressionVisitor;
import java.text.NumberFormat;
import java.util.Locale;
import org.amuthu.expression.Expression;

/**
 * A representation of a value.
 */
public class NumberExpression extends TerminalExpression
{
   // The number's value and typey
   private double value;
   private int type;

   public NumberExpression(boolean value)
   {
      this.value = value ? TRUE : FALSE;
      this.type = BOOLEAN_TYPE;
   }

   public NumberExpression(double value)
   {
      this.value = value;
      this.type = FLOAT_TYPE;
   }

   public NumberExpression(int value)
   {
      this.value = (double) value;
      this.type = INTEGER_TYPE;
   }

   public NumberExpression(double value, int type)
   {
      assert (type == Expression.BOOLEAN_TYPE || type == Expression.FLOAT_TYPE
              || type == Expression.INTEGER_TYPE);

      this.value = value;
      this.type = type;
   }

   public static String toString(int type, double value)
   {
      switch (type)
      {
         case BOOLEAN_TYPE:
            if (value >= TRUE_LEVEL)
            {
               return "true";
            }
            else
            {
               return "false";
            }

         case FLOAT_TYPE:
            return getNumberFormat(value);

         default:
            assert type == INTEGER_TYPE;
            return Integer.toString((int) value);
      }
   }

   @Override
   public String toString()
   {
      return toString(getType(), value);
   }

   /**
    * Returns whether the given expression is a NumberExpression
    * set to the given constant. This is a convenience method often
    * called when printing functions to determine whether the print
    * should print only an abbreviated form, e.g.
    *
    * rsi(45, 0) is printed as rsi().
    *
    * @param expression the expression to query.
    * @param value the value to check
    * @return <code>true<code> if the expression is a <code>NumberExpression</code>
    *         with the given value.
    */
   public static boolean isConstant(Expression expression, int value)
   {
      if (expression instanceof NumberExpression)
      {
         NumberExpression numberExpression = (NumberExpression) expression;

         if ((int) numberExpression.getValue() == value)
         {
            return true;
         }
      }

      return false;
   }

   /**
    * Get the value of the number.
    *
    * @return value
    */
   public double getValue()
   {
      return value;
   }

   /**
    * Set the value of the number.
    *
    * @param value the new value
    */
   public void setValue(double value)
   {
      this.value = value;
   }

   /**
    * Get the type of the expression.
    *
    * @return one of {@link #BOOLEAN_TYPE}, {@link #FLOAT_TYPE} or {@link #INTEGER_TYPE}.
    */
   @Override
   public int getType()
   {
      return type;
   }

   @Override
   public void accept(ExpressionVisitor visitor)
   {
      visitor.visit(this);
   }

   public static String getNumberFormat(double value)
   {
      NumberFormat numFormat = null;

      numFormat = NumberFormat.getInstance(Locale.ENGLISH);
      numFormat.setGroupingUsed(false);
      numFormat.setMinimumIntegerDigits(1);
      numFormat.setMinimumFractionDigits(1);
      numFormat.setMaximumFractionDigits(6);


      return numFormat.format(value);
   }

}
